import 'package:dartkit/dartkit.dart';
import 'package:test/test.dart';

final _time1 = DateTime.now().subtract(Duration(minutes: 60));
final _time2 = DateTime.now().subtract(Duration(minutes: 30));
final _time3 = DateTime.now().subtract(Duration(minutes: 20));
final _time4 = DateTime.now().subtract(Duration(minutes: 2));

const tinyTime = Duration(seconds: 1);

Future<Pomo> createPomo(DateTime begin, DateTime end,
        {int id = idTest}) async =>
    await pomoTable.create({"user_id": id, "begin": begin, "end": end});

void main() {
  prepareAndCleanPostgres("pomo_test_db");

  test("创建与寻找番茄", () async {
    // 原来数据库中没有番茄
    List<Pomo> pomosBefore = await pomoTable.findFor(idTest);
    expect(pomosBefore, isEmpty);
    // 插入一个番茄，并根据它的结束时间寻找
    final pomo = await createPomo(_time1, _time2);
    final Pomo? found = await pomoTable.find(pomo.id);
    // 可以找到和番茄1一模一样的番茄
    expect(found, isNotNull);
    expect(found?.period, pomo.period);
  });

  test("创建时间重叠", () async {
    // 已经创建一个时间的前提下，如果创建了时间上有重叠（1-3和2-4重叠）的番茄，则会报错
    await createPomo(_time1, _time3);
    expect(() async => await createPomo(_time2, _time4), isPostgresBug);
  });

  test("批量寻找", () async {
    // 创建3个番茄，其中2个为默认id
    await createPomo(_time1, _time2);
    await createPomo(_time3, _time4);
    // 创建一个新的用户以生成id 2
    await userTable.create({"phone": "15900582254"});
    await createPomo(_time1, _time2, id: 2);
    // 根据默认id批量查找，能找到2个
    List<Pomo> pomos = await pomoTable.findFor(idTest);
    expect(pomos, hasLength(2));
  });

  test("范围查找", () async {
    // 插入2个番茄（第一个番茄结束时间在30分钟前）
    await createPomo(_time3, _time4);
    // 寻找25分钟前到现在的番茄，能找到1个番茄
    List<Pomo> founds = await pomoTable.findBetween(
      period: Period(_time3.subtract(tinyTime), _time4.add(tinyTime)),
      userId: idTest,
    );
    expect(founds, hasLength(1));
    // 如果不包括头的话就无法找到
    List<Pomo> foundsLackBegin = await pomoTable.findBetween(
      period: Period(_time3.add(tinyTime), _time4.add(tinyTime)),
      userId: idTest,
    );
    expect(foundsLackBegin, isEmpty);
    // 如果不包括尾的话也无法找到
    List<Pomo> foundsLackEnd = await pomoTable.findBetween(
      period: Period(_time3.subtract(tinyTime), _time4.subtract(tinyTime)),
      userId: idTest,
    );
    expect(foundsLackEnd, isEmpty);
  });

  test("更新", () async {
    // 创建一个番茄
    final pomo = await createPomo(_time2, _time3);
    // 将番茄的所有参数都修改一遍，并更新
    pomo.period = Period(_time1, _time4);
    pomo.title = "标题";
    pomo.summary = "总结";
    await pomoTable.update(pomo);
    // 重新寻找番茄，找到的番茄符合修改后的数据
    final Pomo? found = await pomoTable.find(pomo.id);
    expect(found?.period, Period(_time1, _time4));
    expect(found?.title, "标题");
    expect(found?.summary, "总结");
  });

  test("更新不能重叠", () async {
    // 创建2个番茄，其中一个专门用来产生冲突
    await createPomo(_time1, _time2);
    final pomo = await createPomo(_time3, _time4);
    // 将后一个番茄的时间修改成有冲突的样子，这时候应该还是没事的，因为没有保存到数据库
    pomo.period = Period(_time1, _time3);
    // 更新番茄数据，应该收获一个冲突
    expect(() async => await pomoTable.update(pomo), isPostgresBug);
  });

  test("删除", () async {
    // 创建一个番茄，然后删除它
    final pomo = await createPomo(_time2, _time3);
    await pomoTable.delete(pomo.id);
    // 发现无法找到这个番茄
    final Pomo? found = await pomoTable.find(pomo.id);
    expect(found, isNull);
    // 但如果重复删除，则会报错
    expect(() async => await pomoTable.delete(pomo.id), isBug);
  });
}
